/*
 * table_Declarator.c
 *
 *  Created on: 2012/04/26
 *      Author: guanxiaoying
 */

#include "../../parser/coredef.h"
#include "../../parser/cc/cc.h"
typedef struct _DECLARATORTBL {
	AST astNextDeclarator;
	AST astParentDeclarator;
	AST astChildDeclarator;
	AST astDeclaration;
	U2  usDeclaratorKind;
	union {
		AST astBitExp;
		AST astArrayExp;
		AST astMemChain;
		AST initialExp;
		AST astSym;
		UCHAR  num[4];
	}param;
	AST astType;
	AST astCodeScp;
}DECLARATOR, *PDECLARATOR;

#define TableSize  (sizeof(DECLARATOR))
#define TableType  PDECLARATOR
#define stTable stDeclaratorManager.memoryBlocks
#define maxTable stDeclaratorManager.maxRecordNum
#define  maxNumPerBlk  (stDeclaratorManager.astMaxNum_Block)

static TABLEMANAGER stDeclaratorManager = {
//		U4                  usIdx;
		0,
//		PSZ				    con_pszName;    constant
		__FILE__,
//		U2					con_usSize;		constant
		TableSize,
//		U2					block_num;	　　　　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_Block;     １回設定のみ
		0,
//		S4					astTabNum_LastPage; 　　　　Reset clear  際　要
		0,
//		S4					astMaxNum_LastPage;     Reset clear  際　要
		0,
//		U4					ulMaxByte;	　　　　　　　　　　クリアしない
		0,
//		U4					con_minPageSize;　　　　　　　　　　constant
		0
};
static VOID resetListener( U4  procid, U2 index )
{
	if( procid == stDeclaratorManager.u4Idx )
	{
		if( index > 0 && index < MAX_VOLUMN_OF_TABLE )
		{
			stTable[ index-1] = NULL;
		}
	}
}
static TableType core_getTable( AST index )
{
	TableType temp = (TableType)Check_Com( &stDeclaratorManager, resetListener, index );
	if( temp != NULL ){ return &temp[index%maxNumPerBlk]; } return NULL;
}


static BOOL ClearTable( VOID )
{
	return Clear_Com( &stDeclaratorManager );
}
static BOOL ResetTable( VOID )
{
	return Reset_Com( &stDeclaratorManager );
}
static BOOL AllocTable( AST astReqArg )
{
	return AllocTable_Com( &stDeclaratorManager, astReqArg, resetListener );
}
static AST getMaxLineNum( VOID )
{
	return maxTable;
}

/* give up the way that defining get/set function pointer in the struct,
 * because of memory volume.
 */
//ACCESS_U2_FIELD tokenKind;
static U2 getDeclaratorKind( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->usDeclaratorKind;
}
static U2 setDeclaratorKind( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->usDeclaratorKind = value;
}

static AST getNext( AST index  ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astNextDeclarator;
}
static AST setNext( AST index, AST value ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astNextDeclarator = value;
}
//ACCESS_IDX_FIELD  location;
static AST getParent( AST index  ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astParentDeclarator;
}
static AST setParent( AST index, AST value ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astParentDeclarator = value;
}
//ACCESS_IDX_FIELD  codeScp;
static AST getDeclaration( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astDeclaration;
}
static AST setDeclaration( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astDeclaration = value;
}
//ACCESS_IDX_FIELD  macroExtStack;
static AST getBitExp( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_BITFIELD ){
		return 0;
	}
	return pTbl->param.astBitExp;
}
static AST setBitExp( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_BITFIELD ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_BITFIELD;
	return pTbl->param.astBitExp = value;
}
static AST getArrayIdx( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_ARRAY ){
		return 0;
	}
	return pTbl->param.astArrayExp;
}
static AST setArrayIdx( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_ARRAY ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_ARRAY;
	return pTbl->param.astArrayExp = value;
}
static AST getParamDecl( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_FUNC ){
		return 0;
	}
	return pTbl->param.astMemChain;
}
static AST setParamDecl( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_FUNC ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_FUNC;
	return pTbl->param.astMemChain = value;
}
static AST getInitExpList( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_INIT ){
		return 0;
	}
	return pTbl->param.initialExp;
}
static AST setInitExpList( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_INIT ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_INIT;
	return pTbl->param.initialExp = value;
}
static AST getSymbol( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_SYM ){
		return 0;
	}
	return pTbl->param.astSym;
}
static AST setSymbol( AST index, AST value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_SYM ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_SYM;
	return pTbl->param.astSym = value;
}
static U2 getConstNum( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_POINTER ){
		return 0;
	}
	return pTbl->param.num[0];
}
static U2 setConstNum( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_POINTER ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_POINTER;
	return pTbl->param.num[0] = value;
}
static U2 getVolatileNum( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_POINTER ){
		return 0;
	}
	return pTbl->param.num[1];
}
static U2 setVolatileNum( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_POINTER ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_POINTER;
	return pTbl->param.num[1] = value;
}
static U2 getRestrictNum( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != DECLARATOR_POINTER ){
		return 0;
	}
	return pTbl->param.num[2];
}
static U2 setRestrictNum( AST index, U2 value )
{
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	if( pTbl->usDeclaratorKind != 0
		&& ( pTbl->usDeclaratorKind != DECLARATOR_POINTER ) ){
		Throw_MemoryError( &stDeclaratorManager, DATA_SETTING_MISS, index, pTbl->usDeclaratorKind );
	}
	pTbl->usDeclaratorKind = DECLARATOR_POINTER;
	return pTbl->param.num[2] = value;
}
static AST getChild( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astChildDeclarator;
}
static AST setChild( AST index, AST value ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astChildDeclarator = value;
}
static AST getType( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astType;
}
static AST setType( AST index, AST value ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astType = value;
}
static AST getLocation( AST index ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astCodeScp;
}
static AST setLocation( AST index, AST value ){
	TableType pTbl = core_getTable( index );
	if( pTbl == NULL )
	{
		return 0;
	}
	return pTbl->astCodeScp = value;
}
static S4 checkSetting( AST astIndex ){
	TableType pTbl = core_getTable( astIndex );
	if( pTbl == NULL ){
		return -1;
	}
	if( pTbl->usDeclaratorKind == 0 ){
		return 1;
	}
	switch( pTbl->usDeclaratorKind ){
	case  DECLARATOR_POINTER   :
	case  DECLARATOR_ARRAY     :
	case  DECLARATOR_FUNC      :
		break;
	case  DECLARATOR_INIT      :
	case  DECLARATOR_SYM       :
	case  DECLARATOR_PAREN     :
	case  DECLARATOR_BITFIELD  :
		if( pTbl->param.astArrayExp == 0 ){
			return 2;
		}
		break;
	}
	if( pTbl->astCodeScp == 0 ){
		return 3;
	}
	if( pTbl->astType == 0 ){
		return 4;
	}
	if( pTbl->astDeclaration == 0 ){
		return 5;
	}
	return 0;
}
const DECLARATORACCESS stDeclaratorAccess= {
//		BOOL (*clear)( VOID );
		ClearTable,
//		BOOL (*reset)( VOID );
		ResetTable,
//		BOOL (*alloc)( AST );
		AllocTable,
//		AST  (*getMax)( VOID );
		getMaxLineNum,
//		ACCESS_IDX_FIELD  nextDeclarator;
		{
				getNext,
				setNext
		},

//		ACCESS_IDX_FIELD  parentDeclarator;
		{
				getParent,
				setParent
		},

//		ACCESS_IDX_FIELD  declaration;
		{
				getDeclaration,
				setDeclaration
		},
//		ACCESS_U2_FIELD   declaratorKind;
		{
				getDeclaratorKind,
				setDeclaratorKind
		},
//		ACCESS_IDX_FIELD  bitIdx;
		{
				getBitExp,
				setBitExp
		},
//		ACCESS_IDX_FIELD  arrayIdx;
		{
				getArrayIdx,
				setArrayIdx
		},
//		ACCESS_IDX_FIELD  paramChain;
		{
				getParamDecl,
				setParamDecl
		},
//		ACCESS_IDX_FIELD  initialExpList;
		{
				getInitExpList,
				setInitExpList
		},
//		ACCESS_IDX_FIELD  symbol;
		{
				getSymbol,
				setSymbol
		},
//		ACCESS_U2_FIELD   constNum;
		{
				getConstNum,
				setConstNum
		},
//		ACCESS_U2_FIELD   volatileNum;
		{
				getVolatileNum,
				setVolatileNum
		},
//		ACCESS_U2_FIELD   restrictNum;
		{
				getRestrictNum,
				setRestrictNum
		},
//		ACCESS_IDX_FIELD  childDeclarator;		/* 7 */
		{
				getChild,
				setChild
		},
//		ACCESS_IDX_FIELD  type;					/* 8 */
		{
				getType,
				setType
		},
//		ACCESS_IDX_FIELD  codeScp;					/* 9 */
		{
				getLocation,
				setLocation
		},
		checkSetting
};
